package com.dp.server;

import java.util.List;
import java.util.StringTokenizer;

import javassist.expr.Instanceof;

import javax.management.Query;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import com.dp.server.entities.Almacen;
import com.dp.server.entities.Cliente;
import com.dp.server.entities.Conexion;
import com.dp.server.entities.Incidencia;
import com.dp.server.entities.Paquete;

public class MantenimientoGenerico< DBable > {
	public String nombreTabla;
	public static EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
	public static long countQuery( String query , String table ){
		//TODO: probar, aun no se si funciona :D
		long ans = 0;
		//EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		ans = (long)entityManager.createQuery("from "+table +" where eliminado <> true and " + query ).getResultList().size();
		entityManager.close();
		return ans;
	}
	
	public static Object uniqueQuery( String query ){
		Object ans = null;
	//	EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		List<Object> lis = entityManager.createQuery( query ).getResultList();
		entityManager.close();
		if( lis.isEmpty() ) return null;
		return lis.get(0);
	}
	/*
	 * No se olviden que se tiene que tener en cuenta eliminado = 0 dentro del query
	 * sino saldran todos los que fueron eliminados logicamente tb.
	 */
	public static Object query( String query ){
		Object ans = null;
	//	EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		ans = entityManager.createQuery( query ).getResultList();
		entityManager.close();
		return ans;
	}
	public MantenimientoGenerico( String nombreTabla ){
		this.nombreTabla = nombreTabla;
	}
	
	public DBable modifica( DBable obj ){
		return registra( obj );
	}
	/*
	 * registra todos los elementos de la lista en la tabla y hace comits cada freq elementos para que no se muera
	 * la base de datos D:
	 */
	public boolean registrarBatch( List<DBable> lista , int freq ){
	//	EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		entityManager.getTransaction().begin();
		int i = 0;
		//TODO: speedup batch inserts
		for( DBable obj : lista ){
			entityManager.merge( obj );
			if( i % freq == 0 && i != 0 ) entityManager.flush();
			i++;
		}
		entityManager.getTransaction().commit();

		entityManager.close();

		return true;
	}
	
	public DBable registra( DBable obj ) 
	{
		try{
		//	EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
			EntityManager entityManager = entityManagerFactory.createEntityManager();
			entityManager.getTransaction().begin();
			DBable ans = (DBable) entityManager.merge( obj );
			entityManager.getTransaction().commit();
			entityManager.close();
			RegistraIncidencia(obj, ans);
			return ans;
		} catch( Exception ex ){
			return null;
		}
	}
	
	public void RegistraIncidencia(DBable obj , DBable ans)
	{
		StringTokenizer st = new StringTokenizer(obj.getClass().toString(),".");
		st.nextToken();
		st.nextToken();
		st.nextToken();
		st.nextToken();
		String cad = st.nextToken();
		Incidencia incidencia = null;
		switch(cad)
		{
			case "Almacen":
				Almacen almacen = (Almacen)obj;
				Almacen almacen2 = (Almacen)ans;
				if(almacen.getId()==0)
					incidencia = new Incidencia("Se ha registrado un nuevo "+cad+" "+almacen.getDescripcion(), cad, almacen2.getId());
				else
					incidencia = new Incidencia("Se ha modificado un "+cad+" "+almacen.getDescripcion(), cad, almacen2.getId());
				break;
			case "Paquete":
				Paquete paquete = (Paquete)obj;
				Paquete paquete2 = (Paquete)ans;
				if(paquete.getId()==0)
					incidencia = new Incidencia("Se ha registrado un nuevo "+cad+" "+paquete.getDescripcion(), cad, paquete2.getId());
				else
					incidencia = new Incidencia("Se ha modificado un "+cad+" "+paquete.getDescripcion(), cad, paquete2.getId());
				break;
			case "Conexion":
				Conexion conexion = (Conexion)obj;
				Conexion conexion2 = (Conexion)ans;
				if(conexion.getId()==0)
					incidencia = new Incidencia("Se ha registrado una nuevo "+cad+" "+conexion.getDescripcion(), cad, conexion2.getId());
				else
					incidencia = new Incidencia("Se ha modificado una "+cad+" "+conexion.getDescripcion(), cad, conexion2.getId());
				break;
			case "Cliente":
				Cliente cliente = (Cliente)obj;
				Cliente cliente2 = (Cliente)ans;
				if(cliente.getId()==0)
					incidencia = new Incidencia("Se ha registrado una nuevo "+cad+" "+cliente.getNombre()+" "+cliente.getApellido1(), cad, cliente2.getId());
				else
					incidencia = new Incidencia("Se ha modificado una "+cad+" "+cliente.getNombre()+" "+cliente.getApellido1(), cad, cliente2.getId());
				break;
			default:
				break;
		}
		if( incidencia == null ) return;
		//EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		entityManager.getTransaction().begin();
		entityManager.merge(incidencia);
		entityManager.getTransaction().commit();
		entityManager.close();
	}
	
	public List< DBable > list(){
	//	EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		@SuppressWarnings("unchecked")
		List< DBable > lista = entityManager.createQuery("from "+nombreTabla +" where eliminado <> true").getResultList();
		entityManager.close();
		return lista;
	}

	public List<DBable> listarQuery(String query){
	//	EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		List< DBable > lista = entityManager.createQuery("from "+nombreTabla +" where eliminado <> true").getResultList();
		entityManager.close();
		return lista;
	}
	
	public List<DBable> listExtendido(String query){
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		List< DBable > lista = entityManager.createQuery("from "+nombreTabla +" where eliminado <> true "+query).getResultList();
		entityManager.close();
		return lista;
	}
	
	public boolean eliminar(int objID) {
		//EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		entityManager.getTransaction().begin();
		try {
		entityManager.createQuery("update "+nombreTabla+" set eliminado = true where id = " + objID).executeUpdate();
		entityManager.getTransaction().commit();
		} catch( Exception ex ){
			return false;
		} finally {
			entityManager.close();
		}
		return true;
	}

	public DBable buscarID( int id ){
		//EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		
		String query = "from "+nombreTabla+" where eliminado <> true and id = " + id;
		//debe ser diferente de true	
		@SuppressWarnings("unchecked")
		List<DBable> lista = entityManager.createQuery(query).getResultList();
		entityManager.close();
		if( lista.size() == 0 ) return null;
		return lista.get( 0 );
	}
	
	public DBable buscarObjeto(String queryString){
		//EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("some_name_you_choose");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		
		String query = "from "+nombreTabla+" where eliminado <> true "+queryString;
		@SuppressWarnings("unchecked")
		List<DBable> lista = entityManager.createQuery(query).getResultList();
		entityManager.close();
		if( lista.size() == 0 ) return null;
		return lista.get( 0 );
	}
	public boolean existeObjeto(String queryString){
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		String query = "from "+nombreTabla+" where eliminado <> true "+queryString;
		@SuppressWarnings("unchecked")
		List<DBable> lista = entityManager.createQuery(query).getResultList();
		entityManager.close();
		return lista.size()>0 ;
	}
}
